// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.eva.android.widget;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;

import com.eva.android.HttpServiceFactory4A;
import com.eva.framework.dto.DataFromServer;
import com.x52im.rbchat.R;

/**
 * 一个提供了可显示和关闭的加载进度提示的activity父类.
 * <p>
 * 不同于{@link DataLoadableActivity}类，本类默认不使用AsyncTask实现数据的自动请求和加载，
 * 仅提供可显示和关闭的加载进度提示的方法，目的是让子类方便整合ViewModel+LiveData实现数据的异步
 * 加载能力。<br>
 * <p>
 * 建议v8.0版后的新功能界面中尽量使用本类而不是{@link DataLoadableActivity}类，从而获得更健壮
 * 的后台线程与Activity生命周期关系的处理能力。
 *
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @since 8.0
 */
public abstract class DataLoadableActivity2 extends ActivityRoot {

    private final static String TAG = DataLoadableActivity2.class.getSimpleName();

    /** 用于与服务端数据交互的等待过程的无穷进度对话框 */
    protected AProgressDialog pd = null;

    /**
     * 是否在activity被新建时刷新一次界面数据，即调用方
     * 法 {@link #loadData(boolean, String)}1次，true表示是 ，默认是true
     */
    private boolean loadDataOnCreate = true;

    /**
     * {@inheritDoc}
     *
     * @see #init(Bundle)
     * @see #isLoadDataOnCreate()
     * @see #loadData(boolean, String)
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (isLoadDataOnCreate())
            //是否在activity被新建时刷新一次界面数据
            loadData();
    }

    /**
     * 显示加载进度条。
     *
     * @param msg 进度条显示内容，如果为null将使用默认内容显示
     */
    public void showProgress(String msg){
        if(pd == null)
            pd = createProgressDialog(msg);
        else
            pd.setMessage(msg == null?$$(R.string.general_data_loading):msg);
    }

    /**
     * 隐藏加载进度条。
     */
    public void hideProgress(){
        if (pd != null)
            pd.dismiss();
    }

    /**
     * 子类可重写本方法从而实现自已的进度提示对话框实现.
     *
     * @return 返回进度提示用的Dialog实例
     */
    protected AProgressDialog createProgressDialog(String msg) {
        try {
            AProgressDialog pd = new AProgressDialog(this, msg == null?$$(R.string.general_data_loading):msg);
            pd.show();
            return pd;
        } catch (Exception e) {
            Log.w(TAG, e.getMessage(), e);
        }
        return null;
    }

    /**
     * <p>
     * 刷新界面数据的唯一公开方法（默认显示加载进度条）.<br>
     * 子类实现者如要实现自已的逻辑请重写本方法或其调用的方法.<br>
     * <p>
     * 本方法的默认实现是：调用方法 {@link #queryData(boolean, String)}从服务端查询数据.
     * 
     * @see #loadData(boolean, String) 
     */
    public void loadData() {
        loadData(true, null);
    }

    /**
     * <p>
     * 刷新界面数据的唯一公开方法.<br>
     * 子类实现者如要实现自已的逻辑请重写本方法或其调用的方法.<br>
     * <p>
     * 本方法的默认实现是：在独立的处理线程中调用方法 {@link #queryData(boolean, String)}从服务端查询数据.
     *
     * @param showProgress true表示读取网络数据时会显示进度提示，否则不显示
     * @param progressMsg  加载进度条显示内容，如果为null将使用默认内容显示
     */
    public void loadData(boolean showProgress, String progressMsg) {
    //  new QueryDataWorder(showProgress).execute(params);
        queryData(showProgress, progressMsg);
    }

    /**
     * <p>
     * 本方法将由{@link #loadData(boolean, String)}调用，目的是由子类中调用ViewModel实现
     * 收集或组织数据，组织好的数据将由子类中ViewModel的liveData中观察者自已调用方法{@link #queryDataAfter(DataFromServer)}
     * 传给{@link #refreshToView(String)}处理以便显示在界面上.<br><br>
     * <p>
     * 典型应用场景下，该类负责连接服务器并且返回结果，但返回结果具体从何而来也可由子类自行决定。<br><br>
     *
     * @param showProgress true表示读取网络数据时会显示进度提示，否则不显示
     * @param progressMsg  加载进度条显示内容，如果为null将使用默认内容显示
     * @see #loadData(boolean, String)
     */
    protected void queryData(boolean showProgress, String progressMsg){
        if(showProgress)
            showProgress(progressMsg);
    }

    /**
     * 本方法由子类调用，从而实现将{@link #queryData(boolean, String)}中得到的原始服务端返回数据的进一步处理，
     * 并将处理结果通过 {@link #refreshToView(String)} 方法显示在ui上。
     *
     * @param result 服务端http接口的原始返回数据
     */
    protected void queryDataAfter(DataFromServer result){
        // 服务端数据成功返回
        if (checkResultValid(result)) {
            System.out.println("--成功");
            // 取消进度提示
            hideProgress();
//            if (pd != null && pd.isShowing())
//                pd.dismiss();

            // 成功后的调用：详细处理结果数据
            onPostExecuteImpl(((DataFromServer) result).getReturnValue());
        } else {
            System.out.println("--失败");
            hideProgress();
//            if (pd != null)
//                pd.dismiss();

            // 失败后的调用
            onPostExecuteFailImpl(((DataFromServer) result).getReturnValue());
        }
    }

    /**
     * 本方法将在异步任务执行成功后被调用。
     * <p>
     * 本方法具体由 {@link #queryDataAfter(DataFromServer)}调用，用于处理异步任务执行成功后，处理获得的数据结果.
     *
     * @param result 是DataFromServer.getReturnValue()的返回结果
     */
    protected void onPostExecuteImpl(Object result){
        refreshToView((String)result);
    }

    /**
     * 本方法将在异步任务执行失败后被调用（本方法默认什么也不做）。
     * <p>
     * 本方法具体由 {@link #queryDataAfter(DataFromServer)}调用，用于处理异步任务执行成功后，处理获得的数据结果.
     *
     * @param result 是DataFromServer.getReturnValue()的返回结果
     */
    protected void onPostExecuteFailImpl(Object result) {
    }

    /**
     * <p>
     * 典型应用场景下，本方法负责把{@link #loadData(boolean, String)}方法中运行的
     * {@link #queryData(boolean, String)}执行结果对象刷新到UI上。但子类也可自行实现自已的数据展现逻辑。<br><br>
     * <p>
     * 典型应用场景下，本方法用于全新刷新UI数据显示，也是唯一提供给子类进行UI数据设置的方法。
     * </p>
     *
     * @param jsonOfResult 典型应用场景下，用来刷新界面数据显示的数据对象
     * @see #loadData(boolean, String)
     * @see #queryDataAfter(DataFromServer)
     */
    abstract protected void refreshToView(String jsonOfResult);

    /**
     * 是否在activity被新建时刷新一次界面数据，即调用方法 {@link #loadData(boolean, String)}1次.
     *
     * @return true表示是 ，默认是true
     */
    public boolean isLoadDataOnCreate() {
        return loadDataOnCreate;
    }

    /**
     * 设置是否在activity被新建时刷新一次界面数据，即调用方法 {@link #loadData(boolean, String)}1次.
     *
     * @param loadDataOnCreate true表示是 ，默认是true
     */
    public void setLoadDataOnCreate(boolean loadDataOnCreate) {
        this.loadDataOnCreate = loadDataOnCreate;
    }

    /**
     * 检查http服务端接口返回值，并返回检查结果。
     * <p>
     * 本方法默认会调用 {@link HttpServiceFactory4A#isSuccess(DataFromServer, Context)}用于检查
     * 服务端返回对象功能状态，并自动在该对象的sucess=false时给出一个提示信息。
     * <p>如无需在sucess=false时给出提示信息请重写本方法，并用类似实现替换默认实现代码即可：
     * <code>return (result != null && ((DataFromServer)result).isSucess());</code>
     *
     * @param result 服务端接口处理完成后的返回结果对象封装对象，通常它会是{@link DataFromServer}的对象}
     * @return true表示服务端成功处理完成本次接口请求，否则表示处理失败
     */
    protected boolean checkResultValid(DataFromServer result) {
        // 服务端数据成功返回
        return (result != null && HttpServiceFactory4A.isSuccess((DataFromServer) result, this));
    }
}